package com.dingreading.cloud.ssxcx.service.impl;

import com.dingreading.cloud.common.base.R;
import com.dingreading.cloud.common.util.NepUtil;
import com.dingreading.cloud.common.util.MstXcxClassType;
import com.dingreading.cloud.common.util.aliyun.MstCdnUtil;
import com.dingreading.cloud.ssxcx.dto.*;
import com.dingreading.cloud.ssxcx.entity.*;
import com.dingreading.cloud.ssxcx.service.*;
import com.dingreading.cloud.ssxcx.util.DataProcessUtils;
import com.dingreading.cloud.ssxcx.util.XcxAttendClassUtils;
import com.dingreading.cloud.ssxcx.util.XcxEntityUtils;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.time.Duration;
import java.time.Instant;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;

@Service
public class XcxAttendClassServiceImpl implements XcxAttendClassService {
    @Resource
    private DataProcessUtils dataProcessUtils;
    @Resource
    private CmservicesService cmservicesService;
    @Resource
    private SubjectsService subjectsService;
    @Resource
    private MembersService membersService;
    @Resource
    private XcxLessonMaterialsService xcxLessonMaterialsService;
    @Resource
    private SubjectLessonVideoService subjectLessonVideoService;
    @Resource
    private SubjectLessonService subjectLessonService;
    @Resource
    private XcxStudentLearningProgressService xcxStudentLearningProgressService;

    @Override
    public R<Object> getMainSubject(String agencyUid, String storeUid, String studentUid) {
        if (StringUtils.isBlank(agencyUid))
            return R.fail("伙伴uid为空！");
        if (StringUtils.isBlank(storeUid))
            return R.fail("门店uid为空！");
        if (StringUtils.isBlank(studentUid))
            return R.fail("学生信息为空！");
        List<Cmservices> cmservicesList = cmservicesService.getByStudentUid(studentUid);

        if (CollectionUtils.isEmpty(cmservicesList)) {
            return R.fail("该学员没有有效的服务");
        }

        Set<String> subjectUids = cmservicesList.stream()
                .map(Cmservices::getSubjectUid)
                .collect(Collectors.toSet());

        if (CollectionUtils.isEmpty(subjectUids)) {
            return R.fail("该学员的服务未关联任何科目");
        }

        List<SubjectsDto> subjectsDtoList = subjectsService.getByprojectUids(subjectUids);
        return R.ok(subjectsDtoList);
    }

    @Override
    public R<Object> getSubjectTree(String agencyUid, String storeUid, String studentUid, String subjectUid) {
        if (StringUtils.isBlank(agencyUid))
            return R.fail("伙伴uid为空！");
        if (StringUtils.isBlank(storeUid))
            return R.fail("门店uid为空！");
        if (StringUtils.isBlank(studentUid))
            return R.fail("学生信息为空！");
        if (StringUtils.isBlank(subjectUid))
            return R.fail("课程uid为空！");

        List<Cmservices> cmservicesList = cmservicesService.getByStudentUidAndSubjectUid(studentUid, subjectUid);

        if (CollectionUtils.isEmpty(cmservicesList)) {
            return R.fail("该学员没有有效的服务");
        }

        Set<String> subjectUids = cmservicesList.stream()
                // 1. 将每个 Cmservices 对象映射为一个包含 subjectUid 和 stageUid 的 Stream
                .flatMap(service -> Stream.of(service.getSubjectUid(), service.getStageUid()))
                // 2. 过滤掉 null 或空白的字符串
                .filter(StringUtils::isNotBlank)
                // 3. 收集成一个 Set，自动去重
                .collect(Collectors.toSet());


        if (CollectionUtils.isEmpty(subjectUids)) {
            return R.fail("该学员的服务未关联任何科目");
        }

        List<SubjectsDto> subjectsDtoList = subjectsService.getBySubjectUids(subjectUids);
        if (CollectionUtils.isEmpty(subjectsDtoList)) {
            return R.ok(Collections.emptyList());
        }

        // 构建树形结构
        List<SubjectTreeDto> subjectTree = XcxAttendClassUtils.buildTree(subjectsDtoList);
        return R.ok(subjectTree);
    }

    @Override
    public R<Object> getAllSubjectTree(String agencyUid, String storeUid, String studentUid) {
        if (StringUtils.isBlank(agencyUid))
            return R.fail("伙伴uid为空！");
        if (StringUtils.isBlank(storeUid))
            return R.fail("门店uid为空！");
        if (StringUtils.isBlank(studentUid))
            return R.fail("学生信息为空！");
        List<Cmservices> cmservicesList = cmservicesService.getByStudentUid(studentUid);

        if (CollectionUtils.isEmpty(cmservicesList)) {
            return R.fail("该学员没有有效的服务");
        }

        Set<String> subjectUids = cmservicesList.stream()
                // 1. 将每个 Cmservices 对象映射为一个包含 subjectUid 和 stageUid 的 Stream
                .flatMap(service -> Stream.of(service.getSubjectUid(), service.getStageUid()))
                // 2. 过滤掉 null 或空白的字符串
                .filter(StringUtils::isNotBlank)
                // 3. 收集成一个 Set，自动去重
                .collect(Collectors.toSet());

        if (CollectionUtils.isEmpty(subjectUids)) {
            return R.fail("该学员的服务未关联任何科目");
        }

        List<SubjectsDto> subjectsDtoList = subjectsService.getBySubjectUids(subjectUids);
        if (CollectionUtils.isEmpty(subjectsDtoList)) {
            return R.ok(Collections.emptyList());
        }

        // 构建树形结构
        List<SubjectTreeDto> subjectTree = XcxAttendClassUtils.buildTree(subjectsDtoList);
        return R.ok(subjectTree);
    }

    @Override
    public R<Object> getSubjectLessonNum(String agencyUid, String storeUid, String subjectUid) {
        if (StringUtils.isBlank(agencyUid))
            return R.fail("伙伴uid为空！");
        if (StringUtils.isBlank(storeUid))
            return R.fail("门店uid为空！");
        if (StringUtils.isBlank(subjectUid))
            return R.fail("科目阶段uid为空！");

        Subjects subjects = subjectsService.getByUid(subjectUid);
        if (subjects == null)
            return R.fail("科目阶段信息获取失败！");
        if (!subjects.getEnabled().equals(1))
            return R.fail("学科已被禁用！");
        if (!subjects.getLevelEnd().equals(1))
            return R.fail("学科不是最后一级！");

        List<SubjectLessonDto> list = subjectLessonService.getSubjectLessonNum(subjects.getId());
        return R.ok(list);
    }

    @Override
    public R<Object> getBean(String agencyUid, String storeUid, String subjectLessonUid, Integer materialStage, String ip) {
        if (StringUtils.isBlank(agencyUid))
            return R.fail("伙伴uid为空！");
        if (StringUtils.isBlank(storeUid))
            return R.fail("门店uid为空！");
        if (StringUtils.isBlank(subjectLessonUid))
            return R.fail("课节uid为空！");
        if (materialStage == null || (materialStage < MstXcxClassType.BEFORECLASS.getType() || materialStage > MstXcxClassType.EXAM.getType()))
            return R.fail("课节阶段参数无效！");

        List<XcxLessonMaterialsDto> list = xcxLessonMaterialsService.listByLessonUidAndStage(subjectLessonUid, materialStage);

        if (CollectionUtils.isNotEmpty(list)) {
            boolean videoTypeExists = list.stream()
                    .filter(materialsDto -> CollectionUtils.isNotEmpty(materialsDto.getUrls()))
                    .flatMap(materialsDto -> materialsDto.getUrls().stream())
                    .anyMatch(fileDto -> Integer.valueOf(1).equals(fileDto.getVideoType()));

            if (!videoTypeExists) {
                SubjectLessonVideo subjectLessonVideo = subjectLessonVideoService.getByLessonUid(subjectLessonUid);
                if (subjectLessonVideo != null) {
                    XcxMaterialsFilesDto xcxMaterialsFilesDto = new XcxMaterialsFilesDto();
                    xcxMaterialsFilesDto.setUrl(NepUtil.nullToZero(subjectLessonVideo.getUrl()));
                    xcxMaterialsFilesDto.setUrlType(2);
                    xcxMaterialsFilesDto.setVideoTitle("说课视频");

                    xcxMaterialsFilesDto.setVideoType(1);

                    list.forEach(materialsDto -> {
                        if (materialsDto.getUrls() == null) {
                            materialsDto.setUrls(new ArrayList<>());
                        }
                        materialsDto.getUrls().add(xcxMaterialsFilesDto);
                    });
                }
            }

            long expire = MstCdnUtil.getVideoExpire();
            // 使用 forEach 遍历列表，同时处理 urls 和 quizOptions
            list.forEach(materialsDto -> {
                // 1. 处理 urls
                if (CollectionUtils.isNotEmpty(materialsDto.getUrls())) {
                    materialsDto.getUrls().stream()
                            .filter(fileDto -> StringUtils.isNotBlank(fileDto.getUrl()))
                            .forEach(fileDto -> fileDto.setUrl(dataProcessUtils.getXcxUrl(fileDto.getUrl(), ip, expire)));
                }

                // 2.如果 materialStage 是 2 (课中介绍)，则打乱 quizOptions
                if (MstXcxClassType.INCLASS.getType().equals(materialStage) && CollectionUtils.isNotEmpty(materialsDto.getQuizOptions())) {
                    Collections.shuffle(materialsDto.getQuizOptions());
                    materialsDto.getQuizOptions().forEach(quizOptionDto -> {
                        if (StringUtils.isNotBlank(quizOptionDto.getUrl())) {
                            quizOptionDto.setUrl(dataProcessUtils.getXcxUrl(quizOptionDto.getUrl(), ip, expire));
                        }
                    });
                }
            });

            // 对 inMaterials 根据 showOrder 进行正序排列
            if (MstXcxClassType.INCLASS.getType().equals(materialStage)) {
                list.sort(Comparator.comparingInt(XcxLessonMaterialsDto::getShowOrder));
            }
        }

        return R.ok(list);
    }

    @Override
    public R<Object> setLearnRecord(String agencyUid, String storeUid, String studentUid, String subjectLessonUid, Integer materialStage) {
        if (StringUtils.isBlank(agencyUid))
            return R.fail("伙伴uid为空！");
        if (StringUtils.isBlank(storeUid))
            return R.fail("门店uid为空！");
        if (StringUtils.isBlank(studentUid))
            return R.fail("学生信息为空！");
        if (StringUtils.isBlank(subjectLessonUid))
            return R.fail("课节uid为空！");
        if (materialStage == null || (materialStage < MstXcxClassType.BEFORECLASS.getType() || materialStage > MstXcxClassType.EXAM.getType()))
            return R.fail("课节阶段参数无效！");

        Map<String, String> materialUids = dataProcessUtils.getLessonMaterialUids(subjectLessonUid, materialStage);

        String projectUid = materialUids.get(DataProcessUtils.KEY_PROJECT_UID);
        String stageUid = materialUids.get(DataProcessUtils.KEY_STAGE_UID);
        String questionUid = materialUids.get(DataProcessUtils.KEY_QUESTION_UID);

        if (projectUid == null && stageUid == null && questionUid == null)
            return R.ok();

        XcxStudentLearningProgress progress = xcxStudentLearningProgressService.getLatest(studentUid, subjectLessonUid, materialStage);
        MembersDto membersDto = membersService.getByUid(studentUid);
        if (membersDto == null)
            return R.fail("学生信息获取失败！");

        if (progress != null) {
            Date addTime = progress.getAddTime();
            Instant addTimeInstant = addTime.toInstant();
            Instant nowInstant = Instant.now();
            Duration duration = Duration.between(addTimeInstant, nowInstant);
            if (duration.toMinutes() < 5) {
                return R.ok();
            }
        }

        XcxStudentLearningProgress newProgress = XcxEntityUtils.newProgressBean(
                agencyUid, storeUid, studentUid, membersDto.getMemberName(), membersDto.getMob(),
                questionUid, null, null, subjectLessonUid, materialStage, projectUid, stageUid, null
        );

        boolean save = xcxStudentLearningProgressService.save(newProgress);
        return save ? R.ok() : R.fail("学习日志保存失败");
    }
}
